﻿using System.Collections.Concurrent;

namespace GoodAdmin.System;

/// <inheritdoc cref="IExtraUserService"/>
public class ExtraUserService : IExtraUserService, ITransient
{
    private readonly IBaseService _baseService;
    private readonly ISysUserService _sysUserService;
    private readonly IFileService _fileService;
    private readonly ISysImportErrorListService _importErrorListService;
    private readonly ISysOrgService _orgService;

    public ExtraUserService(IBaseService baseService, ISysUserService sysUserService,
        IFileService fileService,
        ISysImportErrorListService importErrorListService, 
        ISysOrgService orgService)
    {
        _baseService = baseService;
        _sysUserService = sysUserService;
        _fileService = fileService;
        _importErrorListService = importErrorListService;
        _orgService = orgService;
    }
    /// <inheritdoc/>
    public async Task AddUser(UserAddInput userInput)
    {
        await _baseService.CheckDataScope(userInput.OrgId);
        await _sysUserService.AddUser(userInput);
    }


    /// <inheritdoc/>
    public async Task UpdateUser(UserUpdateInput userInput)
    {
        await CheckDataScope(userInput.Id);
        await _sysUserService.UpdateUser(userInput);
    }

    /// <inheritdoc/>
    public async Task DeleteUser(List<BaseIdInput> Input)
    {
        var idList= Input.Select(x => x.Id).ToList();
        var userList= await _sysUserService.GetUserList(idList);
        await _baseService.CheckDataScope(userList.Select(u => u.OrgId).ToList());
        await _sysUserService.DeleteUser(Input);
    }

    /// <inheritdoc />
    public async Task<bool> ChangeStatus(BaseIdInput input)
    {
        await CheckDataScope(input.Id);
        var user = await _sysUserService.GetUserById(input.Id);
        //如果当前用户状态为有效，那么就禁用用户
        if (user.Status == CommonConst.STATUS_DISABLE)
        {
            return await _sysUserService.EnableUser(input);
        }
        else
        {
            return await _sysUserService.DisableUser(input);
        }       
    }

    /// <inheritdoc />
    public async Task GrantUserRole(UserRoleInput input)
    {
        await _sysUserService.GrantUserRole(input);
    }
    /// <inheritdoc />
    public async Task<SqlSugarPagedList<SysUser>> Page(UserPageInput input)
    {
        if (!UserManager.SuperAdmin)
        {
            var dataScope = await _baseService.GetUserApiRoleOrgIdByRequest();
            var exp = Expressionable.Create<SysUser>();
            exp.And(u => u.Account != RoleConst.SUPERADMIN);
            //用户ID等于自己
            if (dataScope.Count == 0) exp.And(u => u.Id == UserManager.UserId);
            //用户机构在数据范围内
            else exp.And(u => dataScope.Contains(u.OrgId));
            input.Expression = exp;
        }
        return await _sysUserService.GetUserPage(input);
    }

    /// <inheritdoc />
    public async Task<List<UserSelectorOutput>> GetUserSelector(UserSelectorInput input)
    {
        var dataScope = new List<long>();
        bool isCheckDataScope = false;
        if (!UserManager.SuperAdmin)
        {
            dataScope = await _baseService.GetUserApiRoleOrgIdByRequest();
            isCheckDataScope= true;
        }
        return await _sysUserService.GetUserSelector(input, dataScope, isCheckDataScope);
    }
    /// <inheritdoc />
    public async Task ResetPassword(BaseIdInput input)
    {
        await CheckDataScope(input.Id,true);
        await _sysUserService.ResetPassword(input);
    }

    /// <inheritdoc />
    public async Task ChangePassword(ChangePwdInput input)
    {
        await CheckDataScope(input.Id, true);
        //如果不是超级管理员，且不是自己
        if (!UserManager.SuperAdmin && input.Id != UserManager.UserId)
        {
            throw Oops.Bah(UserErrorCode.U012);
        }
        var user = await _sysUserService.GetUserById(input.Id);
        if (CryptogramUtil.Sm2Decrypt(user.Password) == input.PasswordNew)
            throw Oops.Bah(UserErrorCode.U015);
        await _sysUserService.ChangePassword(input);
    }

    /// <inheritdoc/>
    public FileStreamResult TemplateDownload()
    {
        string fileName = "用户信息导入模板";

        ExcelConfig excelconfig = new()
        {
            FileName = fileName,
            HeadFont = "微软雅黑",
            HeadPoint = 10,
            IsAllSizeColumn = true,
            ColumnHeaderModel = new List<ExcelColumnHeaderModel>(),
            ColumnModel = new List<ExcelColumnModel>()
        };
        var columnList = UtilMethod.GetEntityMetadataToList<UserBatchAdd>();
        foreach (var item in columnList)
        {
            //如果列名是*开头，表示必填，红色字体显示
            excelconfig.ColumnHeaderModel.Add(new ExcelColumnHeaderModel()
            {
                Column = item.FieldName,
                ExcelColumn = item.Comment,
                ForeColor = item.Comment.StartsWith("*") ? IndexedColors.Red : IndexedColors.Black
            });
            excelconfig.ColumnModel.Add(new ExcelColumnModel() { Column = item.FieldName, ExcelColumn = item.Comment });
        }

        FileStreamResult stream = ExcelExportHelper<UserBatchAdd>.Export(new List<UserBatchAdd>(), excelconfig, fileName);
        return stream;
    }

    /// <inheritdoc/>
    public async Task<ExcelImportResult> BatchAddUser(IFormFile file)
    {
        var sysFile = await _fileService.UploadFile(file, FileConst.BatchImport);
        var columnList = UtilMethod.GetEntityMetadataToList<UserBatchAdd>();
        var importData = await ExcelImportHelper.ReadExcelToList<UserBatchAdd>(Path.Combine(sysFile.EnginePath, sysFile.StoragePath), columnList);
        //检查权限
        var (userList, errorList) = await CheckImportDataDataAcope(importData);
        var addErrorList = await _sysUserService.BatchAddUser(userList);
        
        errorList.AddRange(addErrorList);
        var errorCount = errorList.Count;
        var message = $"成功导入{importData.Count-errorCount}条数据，失败{errorCount}条数据";
        var excelImportResult = new ExcelImportResult() { ErrorCount = errorCount, FileName = "批量用户导入错误记录.xlsx", Message = message, IsHasErrorFile = errorCount > 0 };
        if (errorCount > 0)
        {
            SysImportErrorList importErrorList = new() { ErrorList = errorList.ToJson(), MethodName = nameof(BatchAddUser) };
            excelImportResult.ListId = await _importErrorListService.Save(importErrorList);
        }

        return excelImportResult;
    }

    /// <inheritdoc/>
    public async Task<FileStreamResult> ErrorDownload(BaseIdInput input)
    {
        var importErrorList = await _importErrorListService.GetById(input.Id);
        try
        {
            var errorList = importErrorList.ErrorList.ToList<UserBatchAddOutput>();
            var columnList = UtilMethod.GetEntityMetadataToList<UserBatchAddOutput>();
            string fileName = "批量用户导入错误记录";
            ExcelConfig excelconfig = new()
            {
                FileName = fileName,
                HeadFont = "微软雅黑",
                HeadPoint = 10,
                IsAllSizeColumn = true,
                ColumnHeaderModel = new List<ExcelColumnHeaderModel>(),
                ColumnModel = new List<ExcelColumnModel>(),
                Title = "错误记录"
            };
            foreach (var item in columnList)
            {
                //如果列名是*开头，表示必填，红色字体显示
                excelconfig.ColumnHeaderModel.Add(new ExcelColumnHeaderModel()
                {
                    Column = item.FieldName,
                    ExcelColumn = item.Comment,

                });
                excelconfig.ColumnModel.Add(new ExcelColumnModel() { 
                    Column = item.FieldName, ExcelColumn = item.Comment, 
                    ForeColor = item.Comment.StartsWith("*") ? IndexedColors.Red : IndexedColors.Black
                });
            }
            FileStreamResult stream = ExcelExportHelper<UserBatchAddOutput>.Export(errorList, excelconfig, fileName);
            return stream;
        }
        catch (Exception)
        {

            throw;
        }
    }
    /// <summary>
    /// 检查数据范围
    /// </summary>
    /// <param name="UserId"></param>
    /// <param name="CheckSelf">检查是否为自己</param>
    /// <returns></returns>
    private async Task CheckDataScope(long UserId, bool CheckSelf = false)
    {
        if (UserManager.SuperAdmin) return;
        var user = await _sysUserService.GetUserById(UserId);
        UserId = CheckSelf ? UserId : 0;
        await _baseService.CheckDataScope(user.OrgId, UserId);
    }

    /// <summary>
    /// 检查导入数据组织权限
    /// </summary>
    /// <param name="importData"></param>
    /// <returns></returns>
    private async Task<(List<UserBatchAdd>, List<UserBatchAddOutput>)> CheckImportDataDataAcope(List<UserBatchAdd> importData)
    {
        if (importData.Count == 0)
        {
            throw Oops.Bah(UserErrorCode.U014);
        }
        ConcurrentBag<UserBatchAddOutput> errorList = new();
        if (UserManager.SuperAdmin) return (importData, errorList.ToList());
        //检查数据范围权限        
        var sysOrgs = await _orgService.GetOrgList();
        ConcurrentBag<UserBatchAdd> userList = new();
        var dataScope = await _baseService.GetUserApiRoleOrgIdByRequest();
        Parallel.ForEach(importData, item =>
        {
            var errorMessage = string.Empty;
            item.OrgName = item.OrgName.Replace(" ", "").TrimEnd(">").TrimStart(">");
            if (!sysOrgs.Any(o => o.LongName == item.OrgName))
            {
                errorMessage += "系统中不存在该组织;";
            }
            //检查是否有该组织权限
            var orgId = sysOrgs.FirstOrDefault(o => o.LongName == item.OrgName).Id;
            if (!dataScope.Any(it => it == orgId))
            {
                errorMessage += "无权限为该组织增加用户;";
            }
            if (!string.IsNullOrEmpty(errorMessage))
            {
                var errorItem = item.Adapt<UserBatchAddOutput>();
                errorItem.ErrorMessages = errorMessage;
                errorList.Add(errorItem);
            }
            else
            {
                userList.Add(item);
            }
        });
        return (userList.ToList(), errorList.ToList());
    }
}